/*
Title:				AltFontPrev
Author: 			Sam Rayner
More Info: 		http://code.google.com/p/altfontprev/
*/

var AFP = {
	version: "2.0.1",
	releaseDate: "27th July 09",
	infoUrl: "http://code.google.com/p/altfontprev/",
	
	fonts: [],
	sels: [],

	snatchClass: function(target, theClass, altClass) {
		var siblings = target.parentNode.childNodes;
		
		for(var i = 0; i < siblings.length; i++) {
 			siblings[i].className = altClass;
		}
		
		target.className = theClass;
	},
	
	detect: function(font) {
		var fallback = /^default /;
        
    if(fallback.test(font) || font == "times" || font == "times new roman")
    	return true;
	
		var testString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 .!?,:'(};]=/-&%_+*";
		
		var normal = document.createElement("span");
		normal.style.fontFamily = "serif";	
		var normalText = document.createTextNode(testString);
		normal.appendChild(normalText);
		
		var test = document.createElement("span");
		test.style.fontFamily = '"' + font + '",serif';
		var testText = document.createTextNode(testString);
		test.appendChild(testText);
		
		var detect = document.createElement("div");
		detect.id = "afp-detect";
		detect.appendChild(normal);
		detect.appendChild(test);
		
		var body = document.getElementsByTagName("body")[0];
		body.appendChild(detect);
		var normalWidth = normal.offsetWidth;
		var normalHeight = normal.offsetHeight;
		var testWidth = test.offsetWidth;
		var testHeight = test.offsetHeight;	
		body.removeChild(detect);
		
		if(testWidth == normalWidth && testHeight == normalHeight)
			return false;
			
		return true;
	},
	
	getElm: function(suffix) {
		return document.getElementById("afp-" + suffix);
	},
	
	getFonts: function(rule) {
		if(rule.selectorText) {
			var selNum = AFP.sels.length;
			var fontFam = rule.style.fontFamily.toLowerCase();
			
			if(!fontFam) {
				var shorthand = rule.style.font.toLowerCase();
				if(shorthand)
					fontFam = shorthand.substring(shorthand.search(/"|'|\S+,|\S+$/), shorthand.length);
			}
		
			if(fontFam && fontFam != "inherit") {
				AFP.sels[selNum] = rule.selectorText;
				var indFonts = fontFam.split(",");
				AFP.fonts[selNum] = new Array(indFonts.length - 1);
				
				for(var fontNum = 0; fontNum < indFonts.length; fontNum++) {
					indFonts[fontNum] = indFonts[fontNum].replace(/'|"|^\s+|\s+$/g, "");
					AFP.fonts[selNum][fontNum] = indFonts[fontNum];
				}
			}
		}
	},
	
	getCSS: function() {
		for(var i = 0; i < document.styleSheets.length; i++) {
			for(var j = 0; j < document.styleSheets[i].cssRules.length; j++) {
				var rule = document.styleSheets[i].cssRules[j];
				if(rule.style)
					AFP.getFonts(rule);
	
				else {
					for(var k = 0; k < document.styleSheets[i].cssRules[j].cssRules.length; k++) {
						rule = document.styleSheets[i].cssRules[j].cssRules[k];
						if(rule.style)
							AFP.getFonts(rule);
					}
				}
			}
		}
	},

	insLink: function() {
		var linkElm = document.createElement("link");
		linkElm.id = "afp-css";
		linkElm.rel = "stylesheet";
		linkElm.type = "text/css";
		linkElm.href = "http://altfontprev.googlecode.com/svn/trunk/afp.css";
		document.getElementsByTagName("head")[0].appendChild(linkElm);
	},
	
	insStyle: function() {
		var styleElm = document.createElement("style");
		styleElm.id = "afp-fontrules";
		styleElm.type = "text/css";
		document.getElementsByTagName("head")[0].appendChild(styleElm);
	},
	
	insPane: function() {
		var divElm = document.createElement("div");
		divElm.id = "afp-pane";
		
		divElm.innerHTML = [
		'<p id="afp-title"><span></span>AltFontPrev</p>',
		'<form><label for="selector">Selector:</label>',
		'<select name="selector" id="afp-selectors"></select>',
		'</form><ul id="afp-fontlists"></ul>',
		'<form id="afp-custom"><label for="afp-input">Custom:</label><input id="afp-input" type="search" placeholder="Type Font Name"></input></form>',
		'<a id="afp-closeicon" href="#close" title="Close">Close</a>',
		'<a id="afp-infoicon" href="#info" title="Info">Info</a>',
		'<div id="afp-info" class="afp-hide"><span></span>',
		'<p>v' + AFP.version + '<em>(' + AFP.releaseDate + ')</em></p>',
		'<p>Created by <a target="_blank" href="http://samrayner.com/">Sam Rayner</a></p>',
		'<p><a target="_blank" href="' + AFP.infoUrl + '">More Info&hellip;</a></p></div></div>'
		].join('');
		
		document.getElementsByTagName("body")[0].appendChild(divElm);
	},
	
	insSelDropdown: function(dest) {
		for(var selNum = 0; selNum < AFP.sels.length; selNum++) {
			var optionText = document.createTextNode(AFP.sels[selNum]);
			
			var optionElm = document.createElement("option"); 
			optionElm.appendChild(optionText);
			
			AFP.getElm(dest).appendChild(optionElm);
		}
	},
	
	insFontLists: function(dest) {
		for(var selNum = 0; selNum < AFP.sels.length; selNum++) {
		
			var olElm = document.createElement("ol");
		
			for(var fontNum = 0; fontNum < AFP.fonts[selNum].length; fontNum++) {
				var fontName = AFP.fonts[selNum][fontNum];

				if(fontName == "serif" 
 					|| fontName == "sans-serif" 
 					|| fontName == "cursive" 
 					|| fontName == "fantasy" 
 					|| fontName == "monospace") {
					fontName = "default " + fontName;
				}
			
				var aText = document.createTextNode(fontName);
				
				var spanElm = document.createElement("span"); 
				
				if(!AFP.detect(fontName))
					spanElm.className = "afp-missing";
			
				var aElm = document.createElement("a");
				aElm.href = "#" + AFP.fonts[selNum][fontNum].replace(/[\s]/g,"_");
			
				if(fontNum % 2 == 0) {
					aElm.className = "afp-stripe";
				}
				
				aElm.appendChild(aText);
				aElm.appendChild(spanElm);
			
				var innerLiElm = document.createElement("li");		
				innerLiElm.style.fontFamily = AFP.fonts[selNum][fontNum] + ",helvetica,arial,sans-serif";
				innerLiElm.appendChild(aElm);
				
				olElm.appendChild(innerLiElm);
			}
		
			var outerLiElm = document.createElement("li");
			outerLiElm.appendChild(olElm);
			
			AFP.getElm(dest).appendChild(outerLiElm);
		}
	},
	
	insError: function() {
		AFP.getElm("selectors").disabled = true;
		AFP.getElm("input").disabled = true;
		
		optionText = document.createTextNode("Uh oh.");
		var optionElm = document.createElement("option");
		optionElm.appendChild(optionText);
		
		AFP.getElm("selectors").appendChild(optionElm);
		
		var liText = document.createTextNode("Looks like there are no fonts declared...");
		var liElm = document.createElement("li");
		liElm.id = "afp-error";
		liElm.appendChild(liText);
		
		AFP.getElm("fontlists").appendChild(liElm);
	},
	
	insCustomFont: function(fontName) {
		var selIndex = AFP.getElm("selectors").selectedIndex;
		var fontList = AFP.getElm("fontlists").childNodes[selIndex].firstChild;
		
		var spanElm = document.createElement("span"); 
		
		if(!AFP.detect(fontName))
			spanElm.className = "afp-missing";
		
		var aText = document.createTextNode(fontName);
		var aElm = document.createElement("a");
		aElm.className = "afp-stripe";
		aElm.href = "#" + fontName.replace(/\s/g,"_");
		aElm.appendChild(aText);
		aElm.appendChild(spanElm);
		
		var liElm = document.createElement("li");		
		liElm.id = "afp-customfont";
		liElm.style.fontFamily = fontName.toLowerCase() + ",helvetica,arial,sans-serif";
		liElm.appendChild(aElm);
		
		if(AFP.getElm("customfont"))
			AFP.getElm("customfont").parentNode.removeChild(AFP.getElm("customfont"));
		
		AFP.getElm("custom").className = "afp-active";
		fontList.appendChild(liElm);
	},

	showFonts: function(selNum) {
		var selFonts = AFP.getElm("fontlists").childNodes[selNum];
		AFP.snatchClass(selFonts, "afp-show", "afp-hide");
		AFP.getElm("custom").className = "";
		
		if(AFP.getElm("customfont"))
			AFP.getElm("customfont").parentNode.removeChild(AFP.getElm("customfont"));
	},

	applyFont: function(selected) {
		AFP.snatchClass(selected, "afp-current", "");
		
		var liArray = selected.parentNode.childNodes;
		var selIndex = AFP.getElm("selectors").selectedIndex;
		
		for(var i = 0; i < liArray.length; i++) {
			if(liArray[i] == selected) {
				var fontIndex = i;
			}
		}

		var newRule = AFP.sels[selIndex] + " {font-family: ";
		
		if(selected.id == "afp-customfont")
			newRule += AFP.getElm("input").value;
		else
			newRule += AFP.fonts[selIndex][fontIndex];
		
		for(var i = 0; i < AFP.fonts[selIndex].length; i++) {
			newRule += "," + AFP.fonts[selIndex][i];
		}
		
		newRule += "}";
		
		var newRuleText = document.createTextNode(newRule);
		AFP.getElm("fontrules").appendChild(newRuleText);
	},

	onSelSelect: function() {
		AFP.showFonts(AFP.getElm("selectors").selectedIndex);
	},

	onFontClick: function(event) {
		event.preventDefault();
		AFP.applyFont(this);
	},
	
	onCustomSubmit: function(event) {
		event.preventDefault();
		var pattern = /\S/;
		
		if(pattern.test(AFP.getElm("input").value)) {
			AFP.insCustomFont(AFP.getElm("input").value);
			AFP.applyFont(AFP.getElm("customfont"));
			AFP.getElm("customfont").addEventListener("click", AFP.onFontClick, false);
		}
	},

	onCloseClick: function(event) {
		event.preventDefault();
		AFP.getElm("fontrules").parentNode.removeChild(AFP.getElm("fontrules"));
		AFP.getElm("css").parentNode.removeChild(AFP.getElm("css"));
		AFP.getElm("pane").parentNode.removeChild(AFP.getElm("pane"));
		AFP.getElm("js").parentNode.removeChild(AFP.getElm("js"));
	},
	
	onInfoClick: function(event) {
		event.preventDefault();
		if(AFP.getElm("info").className == "afp-hide")
			AFP.getElm("info").className = "afp-show";
		else
			AFP.getElm("info").className = "afp-hide";
	},
	
	addListeners: function() {
		AFP.getElm("selectors").addEventListener("change", AFP.onSelSelect, false);
		
		for(var i = 0; i < AFP.getElm("fontlists").childNodes.length; i++) {
			for(var j = 0; j < AFP.getElm("fontlists").childNodes[i].firstChild.childNodes.length; j++) {
				AFP.getElm("fontlists").childNodes[i].firstChild.childNodes[j].addEventListener("click", AFP.onFontClick, false);
			}
		}
		
		AFP.getElm("custom").addEventListener("submit", AFP.onCustomSubmit, false);
		AFP.getElm("closeicon").addEventListener("click", AFP.onCloseClick, false);
		AFP.getElm("infoicon").addEventListener("click", AFP.onInfoClick, false);
	},

	load: function() {	
		AFP.getCSS();
		AFP.insLink();
		AFP.insStyle();
		AFP.insPane();
	
		if(AFP.sels.length > 0) {
			AFP.insSelDropdown("selectors");
			AFP.insFontLists("fontlists");
		}
		else
			AFP.insError();
	
		AFP.showFonts(0);
		AFP.addListeners();
		
		Drag.init(AFP.getElm("title"), AFP.getElm("pane"));
	}
}

// Huge thankyou to Aaron Boodman for this fantastic bit of code. 
// The Drag object that follows is all Aaron's work. I claim no credit for it.
// You can find it at: http://youngpup.net/projects/dom-drag/
// ---------------------------------------------------------------------------

var Drag = {
	obj : null,

	init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper) {
		o.onmousedown = Drag.start;

		o.hmode = bSwapHorzRef ? false : true ;
		o.vmode = bSwapVertRef ? false : true ;

		o.root = oRoot && oRoot != null ? oRoot : o ;

		if (o.hmode	&& isNaN(parseInt(o.root.style.left	))) o.root.style.left 	= "30px";
		if (o.vmode	&& isNaN(parseInt(o.root.style.top 	))) o.root.style.top		= "30px";
		if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right	= "0px";
		if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";

		o.minX	= typeof minX != 'undefined' ? minX : null;
		o.minY	= typeof minY != 'undefined' ? minY : null;
		o.maxX	= typeof maxX != 'undefined' ? maxX : null;
		o.maxY	= typeof maxY != 'undefined' ? maxY : null;

		o.xMapper = fXMapper ? fXMapper : null;
		o.yMapper = fYMapper ? fYMapper : null;

		o.root.onDragStart = new Function();
		o.root.onDragEnd 	= new Function();
		o.root.onDrag			= new Function();
	},

	start : function(e) {
		var o = Drag.obj = this;
	e = Drag.fixE(e);
	var y = parseInt(o.vmode ? o.root.style.top	: o.root.style.bottom);
	var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
	o.root.onDragStart(x, y);

	o.lastMouseX = e.clientX;
	o.lastMouseY = e.clientY;

	if (o.hmode) {
		if (o.minX != null) o.minMouseX = e.clientX - x + o.minX;
		if (o.maxX != null) o.maxMouseX = o.minMouseX + o.maxX - o.minX;
	} 
	else {
		if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
		if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
	}

	if (o.vmode) {
		if (o.minY != null) o.minMouseY = e.clientY - y + o.minY;
		if (o.maxY != null) o.maxMouseY = o.minMouseY + o.maxY - o.minY;
	} 
	else {
		if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
		if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
	}

	document.onmousemove = Drag.drag;
	document.onmouseup	 = Drag.end;

	return false;
	},

	drag : function(e) {
	e = Drag.fixE(e);
	var o = Drag.obj;

	var ey	= e.clientY;
	var ex	= e.clientX;
	var y = parseInt(o.vmode ? o.root.style.top	: o.root.style.bottom);
	var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
	var nx, ny;

	if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
	if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
	if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
	if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);

	nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
	ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));

	if (o.xMapper)		nx = o.xMapper(y)
	else if (o.yMapper)	ny = o.yMapper(x)

	Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
	Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
	Drag.obj.lastMouseX	= ex;
	Drag.obj.lastMouseY	= ey;

	Drag.obj.root.onDrag(nx, ny);
	return false;
	},

	end : function() {
	document.onmousemove = null;
	document.onmouseup 	= null;
	Drag.obj.root.onDragEnd(parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]), 
							parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
	Drag.obj = null;
	},

	fixE : function(e) {
	if (typeof e == 'undefined') e = window.event;
	if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
	if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
	return e;
	}
}

// ---------------------------------------------------------------------------

window.setTimeout("AFP.load()", 0);